
/**
 *  \file att_internal.h
 *
 *  Module Internal Header File contains structure definitions including tables
 *  maintained by the module
 */

/*
 *  Copyright (C) 2013. Mindtree Ltd.
 *  All rights reserved.
 */

#ifndef _H_ATT_INTERNAL_
#define _H_ATT_INTERNAL_

/* --------------------------------------------- Header File Inclusion */
#include "l2cap.h"
#include "BT_common.h"
#include "BT_att_api.h"
#include "att_fsm.h"
#include "att_fsm_defines.h"
#include "BT_device_queue.h"
#include "fsm_engine.h"

/* --------------------------------------------- Global Definitions */

#if ((defined ATT_CLIENT) || (defined ATT_HNDL_VAL_INDICATION_SUPPORT))
#define ATT_CNFRMD_REQUEST_SUPPORT
#endif /* (ATT_CLIENT || ATT_HNDL_VAL_INDICATION_SUPPORT) */

#if ((defined ATT_READ_REQUEST_SUPPORT) || (defined ATT_READ_BLOB_SUPPORT))
#define ATT_READ_RSP_SUPPORT
#endif /* ATT_READ_REQUEST_SUPPORT || ATT_READ_BLOB_SUPPORT */

#if ((defined ATT_WRITE_REQUEST_SUPPORT) ||\
    ((defined ATT_CLIENT) && (defined ATT_HNDL_VAL_INDICATION_SUPPORT) ||\
    (defined ATT_QUEUED_WRITE_SUPPORT)))
#define ATT_NO_PARAMETER_PDU_SUPPORT
#endif

#if (((defined ATT_HNDL_VAL_INDICATION_SUPPORT) ||\
    (defined ATT_HNDL_VAL_NOTIFICATION_SUPPORT)) ||\
    ((defined ATT_CLIENT) && ((defined ATT_WRITE_REQUEST_SUPPORT) ||\
    (defined ATT_WRITE_COMMAND_SUPPORT))))
#define ATT_HNDL_VAL_PARAMETER_PDU_SUPPORT
#endif

/* Determine direction of PDU when posted to the FSM engine */
#define ATT_APPL_INITIATED_PDU           0x00
#define ATT_PEER_INITIATED_PDU           0x01

/* Initializing values for internal table fields */
#define ATT_EXPECTED_RSP_INIT_VAL        0x00

/**
 * Abstracts Size of well defined ATT entities like the Handle, Handle Range,
 * UUID16, UUID128
 */
#define ATT_ATTR_HANDLE_SIZE                 2
#define ATT_ATTR_HANDLE_RANGE_SIZE           4
#define ATT_UUID16_SIZE                      2
#define ATT_UUID128_SIZE                    16
#define ATT_UUID16_HANDLE_PAIR_LEN\
        (ATT_ATTR_HANDLE_SIZE + ATT_UUID16_SIZE)
#define ATT_UUID128_HANDLE_PAIR_LEN\
        (ATT_ATTR_HANDLE_SIZE + ATT_UUID128_SIZE)

/* Lengths of PDUs */
#define ATT_ERR_RSP_LEN                      5
#define ATT_XCHNG_MTU_LEN                    3
#define ATT_WRITE_RSP_LEN                    1

/* Offsets of PDU Fields */
#define ATT_PDU_DATA_OFFSET                  1
#define ATT_FIND_INFO_RSP_DATA_OFFSET        2
#define ATT_READ_BY_TYPE_RSP_DATA_OFFSET     2
#define ATT_READ_BY_GROUP_RSP_DATA_OFFSET    2
#define ATT_ERR_RSP_OP_CODE_OFFSET           1
#define ATT_ERR_RSP_HANDLE_OFFSET            2
#define ATT_ERR_RSP_ERR_CODE_OFFSET          4
#define ATT_XCHNG_MTU_OFFSET                 1
#define ATT_FIND_INFO_UUID_FRMT_OFFSET       1
#define ATT_READ_BY_TYPE_LENGH_OFFSET        1

#ifdef ATT_NO_DEBUG
#define ATT_ERR          BT_debug_null
#else /* ATT_NO_DEBUG */
#ifdef VAR_ARG_IN_MACRO_NOT_SUPPORTED
#define ATT_ERR
#else
#define ATT_ERR(...)     BT_debug_error(BT_MODULE_ID_ATT, __VA_ARGS__)
#endif /* VAR_ARG_IN_MACRO_NOT_SUPPORTED */
#endif /* ATT_NO_DEBUG */

#ifdef ATT_DEBUG
#ifdef VAR_ARG_IN_MACRO_NOT_SUPPORTED
#define ATT_TRC
#define ATT_INF

#define ATT_debug_dump_bytes(data, datalen)

#else
#define ATT_TRC(...)     BT_debug_trace(BT_MODULE_ID_ATT,__VA_ARGS__)
#define ATT_INF(...)     BT_debug_info(BT_MODULE_ID_ATT,__VA_ARGS__)

#define ATT_debug_dump_bytes(data, datalen) BT_debug_dump_bytes(BT_MODULE_ID_ATT, (data), (datalen))

#endif /* VAR_ARG_IN_MACRO_NOT_SUPPORTED */
#else /* ATT_DEBUG */
#define ATT_TRC          BT_debug_null
#define ATT_INF          BT_debug_null

#define ATT_debug_dump_bytes(data, datalen)

#endif /* ATT_DEBUG*/

/**
 *  Locks the ATT Mutex which prevents any global variable being
 *  overwritten by any function. It returns an error if mutex lock fails.
 */
#define ATT_LOCK()\
    BT_MUTEX_LOCK(att_mutex, ATT)

/**
 *  Locks the ATT_mutex which prevents any global variable being
 *  overwritten by any function. To be used in void function as it
 *  returns no error.
 */
#define ATT_LOCK_VOID()\
        BT_MUTEX_LOCK_VOID(att_mutex, ATT)

/**
 *  Unlocks the ATT_mutex which realeses the global variables
 *  to be written into. It returns an error if mutex unlock fails.
 */
#define ATT_UNLOCK()\
    BT_MUTEX_UNLOCK(att_mutex, ATT)

/**
 *  Unlocks the ATT_mutex which realeses the global variables
 *  to be written into. To be used in void functions as it returns
 *  no error.
 */
#define ATT_UNLOCK_VOID()\
        BT_MUTEX_UNLOCK_VOID(att_mutex, ATT)

#define att_alloc_mem(size)\
        BT_alloc_mem(size)

#define att_free_mem(ptr)\
        BT_free_mem(ptr)

#if (ATT_MAX_CONNECTION_INSTANCES < BT_MAX_REMOTE_DEVICES)
#define ATT_CHECK_INSTANCE_ALLOC_FAILURE(i)\
        if (ATT_CON_ID_INIT_VAL == (i))\
        {\
             ATT_ERR (\
             "[ATT]: Failed to allocate ATT instance for new device\n");\
             ATT_UNLOCK_VOID();\
             return;\
        }
#else /* ATT_MAX_CONNECTION_INSTANCES < BT_MAX_REMOTE_DEVICES */
#define ATT_CHECK_INSTANCE_ALLOC_FAILURE(i)
#endif /* ATT_MAX_CONNECTION_INSTANCES < BT_MAX_REMOTE_DEVICES */

#define ATT_L2CAP_NULL_DATA_CHECK(ev,d,dl)\
        if ((L2CAP_FIXED_CH_DATA_RX_EVENT == (ev)) &&\
        ((NULL == (d)) || (0 == (dl))))\
        {\
            /* NULL or zero length data received from L2CAP! */\
            ATT_ERR (\
            "NULL Data Received from L2CAP!\n");\
            return;\
        }

#ifdef ATT_NO_PARAM_CHECK
#define ATT_NO_NULL_PARAM_CHECK
#endif /* ATT_NO_PARAM_CHECK */

#ifdef ATT_NO_NULL_PARAM_CHECK

#define ATT_NULL_CHECK(x)
#define ATT_L2CAP_EVENT_TYPE_CHECK(x)
#define ATT_CHECK_NULL_VALUE(x)
#define ATT_CHECK_NULL_PARAM_VALUE(x)
#define ATT_NULL_CHECK_VOID(x)

#else /* ATT_NO_NULL_PARAM_CHECK */

/* Null Check for ATT API Parameters */
#define ATT_NULL_CHECK ATT_CHECK_NULL_VALUE

#define ATT_L2CAP_EVENT_TYPE_CHECK(x)\
        if (L2CAP_FIXED_CH_MAX_EVENT < (x))\
        {\
            ATT_ERR (\
            "[ATT]: Unknown/Unhandled L2CAP Event 0x%02X received\n",(x));\
            return;\
        }

#define ATT_CHECK_NULL_VALUE(x)\
        if (NULL == (x))\
        {\
            ATT_ERR (\
            "[ATT]: NULL Parameter Unacceptable\n");\
            return ATT_NULL_PARAMETER_NOT_ALLOWED;\
        }

#define ATT_CHECK_NULL_PARAM_VALUE(x)\
        if ((0 != (x)->len) && (NULL == (x)->val))\
        {\
            ATT_ERR (\
            "[ATT]: NULL Parameter Unacceptable\n");\
            return ATT_NULL_PARAMETER_NOT_ALLOWED;\
        }

#define ATT_NULL_CHECK_VOID(x)\
        if (NULL == (x))\
        {\
            ATT_ERR (\
            "[ATT]: NULL Parameter Unacceptable\n");\
            return;\
        }
#endif /* ATT_NO_NULL_PARAM_CHECK */

#define ATT_VALIDATE_INSTANCE(x)\
     if (ATT_MAX_CONNECTION_INSTANCES  <= (x)->att_id)\
     {\
         ATT_ERR (\
         "[ATT]:[0x%02X]: Invalid Instance\n",(x)->att_id);\
         return ATT_INVALID_INSTANCE;\
     }

#define ATT_CHECK_LIST_COUNT(x)\
        if(0 == (x))\
        {\
            ATT_ERR (\
            "[ATT]: No Elements in the list\n");\
            return ATT_INVALID_PARAMETER;\
        }

#define ATT_CHECK_VALUE_LENGTH(x)\
        if (0 == (x))\
        {\
            ATT_ERR (\
            "[ATT]: Invalid Zero Length Value\n");\
            return ATT_INVALID_PARAMETER;\
        }

#define ATT_CHECK_ATTR_HANDLE(x)\
        if (ATT_INVALID_ATTR_HANDLE_VAL == (x))\
        {\
            ATT_ERR (\
            "[ATT]: Invalid DB Handle\n");\
            return ATT_INVALID_PARAMETER;\
        }

#define ATT_ACCESS_STATE(inst)\
        att_connections[(inst)].state

#ifdef VAR_ARG_IN_MACRO_NOT_SUPPORTED
#define ATT_TS_FEED_STATE_INFO
#else
#define ATT_TS_FEED_STATE_INFO(...)
#endif /* VAR_ARG_IN_MACRO_NOT_SUPPORTED */

#ifdef ATT_MTU_UPDATE
#define ATT_INSTANCE_ACCESS_MTU(inst)\
        att_connections[(inst)].mtu

#define ATT_INIT_MTU(inst)\
        ATT_INSTANCE_ACCESS_MTU(inst) = ATT_DEFAULT_MTU

#define ATT_INSTANCE_ACCESS_LTEMP_MTU(inst)\
        att_connections[(inst)].ltemp_mtu

#define ATT_INSTANCE_ACCESS_RTEMP_MTU(inst)\
        att_connections[(inst)].rtemp_mtu

#define ATT_INSTANCE_INIT_LTEMP_MTU(inst)\
        att_connections[(inst)].ltemp_mtu = ATT_DEFAULT_MTU

#define ATT_INSTANCE_INIT_RTEMP_MTU(inst)\
        att_connections[(inst)].rtemp_mtu = ATT_DEFAULT_MTU

#define ATT_INSTANCE_SET_LTEMP_MTU(inst,mtu)\
        att_connections[(inst)].ltemp_mtu = (mtu)

#define ATT_INSTANCE_SET_RTEMP_MTU(inst,mtu)\
        att_connections[(inst)].rtemp_mtu = (mtu)

#else /* ATT_MTU_UPDATE */
#define ATT_INSTANCE_ACCESS_MTU(inst) ATT_DEFAULT_MTU
#define ATT_INIT_MTU(inst)
#define ATT_INSTANCE_ACCESS_LTEMP_MTU(inst) ATT_DEFAULT_MTU
#define ATT_INSTANCE_ACCESS_RTEMP_MTU(inst) ATT_DEFAULT_MTU
#define ATT_INSTANCE_INIT_LTEMP_MTU(inst) ATT_DEFAULT_MTU
#define ATT_INSTANCE_INIT_RTEMP_MTU(inst) ATT_DEFAULT_MTU
#define ATT_INSTANCE_SET_LTEMP_MTU(inst,mtu)
#define ATT_INSTANCE_SET_RTEMP_MTU(inst,mtu)
#endif /* ATT_MTU_UPDATE */

#define ATT_INSTANCE_ACCESS_DEVICE_ID(inst)\
        (att_connections[(inst)].device_id)

#ifdef ATT_ON_BR_EDR_SUPPORT

#define ATT_ACCESS_LCID(inst)\
        (att_connections[(inst)].lcid)

#ifdef L2CAP_SUPPORT_ECBFC_MODE
#define ATT_ACCESS_LMPS(inst)\
        (att_connections[(inst)].l_mps)

#define ATT_ACCESS_RMPS(inst)\
        (att_connections[(inst)].r_mps)
#endif /* L2CAP_SUPPORT_ECBFC_MODE */

#define ATT_INIT_LCID(inst)\
        ATT_ACCESS_LCID(inst) = L2CAP_ATT_CID

#else /* ATT_ON_BR_EDR_SUPPORT */

#define ATT_ACCESS_LCID(inst)
#define ATT_INIT_LCID(inst)

#endif /* ATT_ON_BR_EDR_SUPPORT */

#ifdef ATT_CNFRMD_REQUEST_SUPPORT

#define ATT_INIT_TIMER_HANDLE(inst)\
        att_connections[(inst)].timer_handle = BT_TIMER_HANDLE_INIT_VAL

#define ATT_START_TIMER(inst,param,param_len)\
        ATT_TRC (\
        "[ATT]:[0x%02X]: Request to Start Timer\n",(inst));\
        if (BT_TIMER_HANDLE_INIT_VAL == att_connections[(inst)].timer_handle)\
        {\
            API_RESULT   r_val;\
            \
            ATT_TRC (\
            "[ATT]:[0x%02X]: Starting Timer.",(inst));\
            r_val = BT_start_timer\
                    (\
                        &att_connections[(inst)].timer_handle,\
                        ATT_RESPONSE_TIMEOUT,\
                        att_timer_cb,\
                        (param),\
                        (param_len)\
                    );\
            if (API_SUCCESS != r_val)\
            {\
                ATT_ERR (\
                "[ATT]:[0x%02X]: Failed to Start Timer, Reason 0x%04X",\
                (inst),r_val);\
            }\
            else\
            {\
                ATT_TRC (\
                "[ATT]:[0x%02X]: StartedTimer for 0x%04X seconds",\
                (inst),ATT_RESPONSE_TIMEOUT);\
            }\
        }

#define ATT_STOP_TIMER(inst)\
        ATT_TRC (\
        "[ATT]:[0x%02X]: Request to Stop Timer\n",(inst));\
        if (BT_TIMER_HANDLE_INIT_VAL != att_connections[(inst)].timer_handle)\
        {\
            ATT_TRC (\
            "[ATT]:[0x%02X]: Stopping timer.",(inst));\
            BT_stop_timer(att_connections[(inst)].timer_handle);\
            att_connections[(inst)].timer_handle = BT_TIMER_HANDLE_INIT_VAL;\
        }
#else /* ATT_CNFRMD_REQUEST_SUPPORT */
#define ATT_INIT_TIMER_HANDLE(inst)
#define ATT_START_TIMER(inst,param,param_len)
#define ATT_STOP_TIMER(inst)
#endif /* ATT_CNFRMD_REQUEST_SUPPORT */

#ifdef ATT_ON_ECBFC_SUPPORT
#define ATT_ACCESS_CHANNEL_MODE(inst)\
        (att_connections[(inst)].channel_mode)

#define ATT_INIT_CHANNEL_MODE(inst)\
        ATT_ACCESS_CHANNEL_MODE(inst) = 0x00
#else
#define ATT_INIT_CHANNEL_MODE(inst)
#endif /* ATT_ON_ECBFC_SUPPORT */

#define ATT_INIT_CONNECTION_INSTANCE(inst)\
        ATT_INIT_TIMER_HANDLE(inst);\
        ATT_ACCESS_STATE(inst) = SL_0_IDLE;\
        ATT_INIT_MTU(inst);\
        ATT_INIT_LCID (inst);\
        ATT_INSTANCE_INIT_LTEMP_MTU(inst);\
        ATT_INSTANCE_INIT_RTEMP_MTU(inst);\
        ATT_INIT_APPL_EXPECTED_RSP(inst);\
        ATT_INIT_APPL_EXPECTED_IND_RSP(inst);\
        ATT_INIT_PEER_EXPECTED_RSP(inst);\
        ATT_INIT_CHANNEL_MODE(inst)

#ifdef ATT_ON_BR_EDR_SUPPORT
#define ATT_SET_BR_EDR_DEFAULT_MTU(inst)\
        ATT_INSTANCE_ACCESS_MTU(inst) = L2CAP_MIN_MTU
#endif /* ATT_ON_BR_EDR_SUPPORT */

#ifdef ATT_ON_ECBFC_SUPPORT
#define ATT_SET_ECBFC_DEFAULT_MTU(inst)\
        ATT_INSTANCE_ACCESS_MTU(inst) = L2CAP_MIN_ECBFC_MTU

#define ATT_SET_ECBFC_CHANNEL_MODE(inst)\
        ATT_ACCESS_CHANNEL_MODE(inst) = L2CAP_MODE_ECBFC
#endif /* ATT_ON_ECBFC_SUPPORT */

#define ATT_PACK_1_BYTE_PARAM(buf,offset,val)\
        BT_PACK_LE_1_BYTE\
        (\
            ((UCHAR *)(buf)+L2CAP_HDR_LEN+(offset)),\
            (val)\
        )

#define ATT_PACK_2_BYTE_PARAM(buf,offset,val)\
        BT_PACK_LE_2_BYTE\
        (\
            ((UCHAR *)(buf)+L2CAP_HDR_LEN+(offset)),\
            (val)\
        )

#define ATT_PACK_VALUE(buf,offset,val,len)\
        BT_mem_copy (((UCHAR *)(buf)+(offset)+L2CAP_HDR_LEN),(val),(len))

#define ATT_CHECK_IF_REQUEST(type)\
        ((0x01 == ((type) & 0x01))? BT_FALSE : BT_TRUE)

#define ATT_CHECK_IF_UNCONFIRMED_PDU(type)\
        (((ATT_WRITE_CMD == (type)) || (ATT_SIGNED_WRITE_CMD == (type))\
        || (ATT_HANDLE_VALUE_NTF == (type)))? BT_TRUE : BT_FALSE)


#ifndef BT_EATT
/* TBD:
 * Should the responses be disallowed, but ATT Server support is mandatory
 * for client!
 */
#define ATT_CHECK_SUPPORTED_PDU(pdu)\
        (((((pdu) > 0x13) && ((pdu) < 0x16)) ||\
        (((pdu) > 0x1E) && (((pdu) != ATT_SIGNED_WRITE_CMD) &&\
        ((pdu) != ATT_WRITE_CMD)))) ? BT_FALSE : BT_TRUE)
#else
#define ATT_CHECK_SUPPORTED_PDU(pdu)\
        (((((pdu) > 0x13) && ((pdu) < 0x16)) ||\
        (((pdu) > 0x1E) && ((pdu) < 0x20)) ||\
        (((pdu) > 0x21) && ((pdu) < 0x23)) ||\
        (((pdu) > 0x23) && (((pdu) != ATT_SIGNED_WRITE_CMD) &&\
        ((pdu) != ATT_WRITE_CMD)))) ? BT_FALSE : BT_TRUE)
#endif /* BT_EATT */

#ifdef ATT_NO_PARAM_CHECK
#define ATT_VALIDATE_PDU_TYPE_SUPPROTED(type)
#else /* ATT_NO_PARAM_CHECK */
#define ATT_VALIDATE_PDU_TYPE_SUPPROTED(type)\
        if (BT_FALSE == ATT_CHECK_SUPPORTED_PDU(type))\
        {\
            ATT_ERR (\
            "[ATT]: Unsupported Procedure 0x%02X", (type));\
            \
            return ATT_UNKNOWN_PDU_TYPE;\
        }
#endif /* ATT_NO_PARAM_CHECK */

#define ATT_IN_TX_TRASANCTION(hndl)\
        ((SL_0_IN_TX_TRANSACTION == (SL_0_IN_TX_TRANSACTION & \
        ATT_ACCESS_STATE(hndl)))? BT_TRUE : BT_FALSE)

#define ATT_SET_FSM_EVENT_TYPE(fsm_event,op_code)\
        (fsm_event) = att_get_fsm_event((op_code))

#define ATT_GET_APPL_EXPECTED_RSP(hndl)\
        att_connections[(hndl)].expected_tx_rsp

#define ATT_GET_APPL_EXPECTED_IND_RSP(hndl)\
        att_connections[(hndl)].expected_tx_ind_rsp

#define ATT_INIT_APPL_EXPECTED_RSP(hndl)\
        ATT_GET_APPL_EXPECTED_RSP(hndl) = ATT_EXPECTED_RSP_INIT_VAL

#define ATT_INIT_APPL_EXPECTED_IND_RSP(hndl)\
        ATT_GET_APPL_EXPECTED_IND_RSP(hndl) = ATT_EXPECTED_RSP_INIT_VAL

#ifdef ATT_CNFRMD_REQUEST_SUPPORT
#define ATT_INIT_PEER_EXPECTED_RSP(hndl)\
        ATT_GET_PEER_EXPECTED_RSP(hndl) = ATT_EXPECTED_RSP_INIT_VAL

#define ATT_GET_PEER_EXPECTED_RSP(hndl)\
        att_connections[(hndl)].expected_rx_rsp

#else /* ATT_CNFRMD_REQUEST_SUPPORT */
#define ATT_INIT_PEER_EXPECTED_RSP(hndl)
#define ATT_GET_PEER_EXPECTED_RSP(hndl)
#endif /* ATT_CNFRMD_REQUEST_SUPPORT */

#ifdef ATT_HNDL_VAL_INDICATION_SUPPORT
#define ATT_CHECK_IF_INDICATION(pdu_id)\
        ((ATT_HANDLE_VALUE_IND == (pdu_id))? BT_TRUE: BT_FALSE)
#else /* ATT_HNDL_VAL_INDICATION_SUPPORT */
#define ATT_CHECK_IF_INDICATION(pdu_id) BT_TRUE
#endif /*  ATT_HNDL_VAL_INDICATION_SUPPORT */

#define ATT_CHECK_IF_NOTIFICATION(pdu_id)\
        (((ATT_HANDLE_VALUE_NTF == (pdu_id)) || (ATT_HANDLE_VALUE_MULTIPLE_NTF == (pdu_id)))? BT_TRUE: BT_FALSE)

#ifdef ATT_HNDL_VAL_INDICATION_SUPPORT
#define ATT_CHECK_IF_HNDL_VAL_CNFRM(pdu_id)\
       ((ATT_HANDLE_VALUE_CNF == (pdu_id))? BT_TRUE: BT_FALSE)
#else /* ATT_HNDL_VAL_INDICATION_SUPPORT */
#define ATT_CHECK_IF_HNDL_VAL_CNFRM(pdu_id) BT_TRUE
#endif /* ATT_HNDL_VAL_INDICATION_SUPPORT */

#define ATT_CHECK_IF_ERROR_RSP(pdu_id)\
        ((ATT_ERROR_RSP == (pdu_id))? BT_TRUE: BT_FALSE)

#define ATT_CHECK_IF_WRITE_COMMAND(pdu_id)\
        ((ATT_WRITE_CMD == (pdu_id))? BT_TRUE: BT_FALSE)

#define ATT_CHECK_IF_SIGNED_WRITE_COMMAND(pdu_id)\
        ((ATT_SIGNED_WRITE_CMD == (pdu_id))? BT_TRUE: BT_FALSE)

#define ATT_CHECK_IF_EXPECTED_APPL_RESPONSE(hndl,type)\
        ((ATT_CHECK_IF_ERROR_RSP(type)||\
        ((type) == ATT_GET_APPL_EXPECTED_RSP(hndl)))? BT_TRUE : BT_FALSE)

#define ATT_CHECK_IF_EXPECTED_PEER_RESPONSE(hndl,type)\
        ((ATT_CHECK_IF_ERROR_RSP(type)||\
        ((type) == ATT_GET_PEER_EXPECTED_RSP(hndl)))? BT_TRUE : BT_FALSE)

#define ATT_CHECK_IF_PEER_RESPONSE_AWAITED(hndl)\
        ((ATT_EXPECTED_RSP_INIT_VAL == ATT_GET_PEER_EXPECTED_RSP(hndl))? BT_FALSE:\
        BT_TRUE)

#define ATT_CHECK_IF_INVALID_ATTR_HANDLE(attr_hndl)\
        (ATT_INVALID_ATTR_HANDLE_VAL == (attr_hndl))

/* Validation of ATT MTU received from peer implementation */
#define ATT_CHECK_REMOTE_MTU_SIZE(mtu)\
        (((mtu) < ATT_DEFAULT_MTU)? BT_FALSE: BT_TRUE)

/* Validation of ATT MTU sent by local implementation */
#define ATT_CHECK_LOCAL_MTU_SIZE(mtu)\
        ((((mtu) < ATT_DEFAULT_MTU) ||((mtu) > ATT_MAX_MTU))? BT_FALSE: BT_TRUE)

#define ATT_CHECK_MTU_FULL(id,cur_len,len_to_add)\
        ((((cur_len) + (len_to_add)) > \
        ATT_INSTANCE_ACCESS_MTU((id)))? \
        BT_TRUE : BT_FALSE)

#ifdef ATT_SUPPORT_128_BIT_UUID
#define ATT_CHECK_UUID_FORMAT(frmt)\
        (((ATT_16_BIT_UUID_FORMAT == (frmt)) ||\
        (ATT_128_BIT_UUID_FORMAT == (frmt)))? BT_TRUE : BT_FALSE)

#define ATT_GET_UUID_LEN(frmt)\
        ((ATT_16_BIT_UUID_FORMAT == (frmt))? ATT_UUID16_SIZE : ATT_UUID128_SIZE)

#define ATT_GET_UUID_HANDLE_PAIR_LEN(frmt)\
        ((ATT_16_BIT_UUID_FORMAT == (frmt))? ATT_UUID16_HANDLE_PAIR_LEN:\
        ATT_UUID128_HANDLE_PAIR_LEN)

#define ATT_PACK_UUID(buf,offset,uuid,frmt)\
        if(ATT_16_BIT_UUID_FORMAT == (frmt))\
        {\
            ATT_PACK_2_BYTE_PARAM((buf),(offset),uuid.uuid_16);\
        }\
        else\
        {\
            ATT_PACK_VALUE((buf),(offset),uuid.uuid_128.value,ATT_UUID128_SIZE);\
        }

#else /* ATT_SUPPORT_128_BIT_UUID */
#define ATT_CHECK_UUID_FORMAT(frmt)\
        ((ATT_16_BIT_UUID_FORMAT == (frmt))? BT_TRUE : BT_FALSE)

#define ATT_GET_UUID_LEN(frmt)  (ATT_UUID16_SIZE)

#define ATT_GET_UUID_HANDLE_PAIR_LEN(frmt)\
        ATT_UUID16_HANDLE_PAIR_LEN

#define ATT_PACK_UUID(buf,offset,uuid,frmt)\
        ATT_PACK_2_BYTE_PARAM((buf),(offset),(uuid))

#endif /* ATT_SUPPORT_128_BIT_UUID */

#define ATT_PACK_OP_CODE(buf,op_code)\
        ATT_PACK_1_BYTE_PARAM((buf),(0),(op_code))

#define ATT_PACK_ERR_RSP_OP_CODE(buf,op_code)\
        ATT_PACK_1_BYTE_PARAM((buf),(ATT_ERR_RSP_OP_CODE_OFFSET),(op_code))

#define ATT_PACK_ERR_RSP_HANDLE(buf,handle)\
        ATT_PACK_2_BYTE_PARAM((buf),(ATT_ERR_RSP_HANDLE_OFFSET),(handle))

#define ATT_PACK_ERR_RSP_ERR_CODE(buf,err_code)\
        ATT_PACK_1_BYTE_PARAM ((buf),(ATT_ERR_RSP_ERR_CODE_OFFSET),(err_code))

#define ATT_PACK_XCHNG_MTU(buf,mtu)\
        ATT_PACK_2_BYTE_PARAM((buf),(ATT_XCHNG_MTU_OFFSET),(mtu))

#define ATT_PACK_UUID_FRMT(buf,frmt)\
        ATT_PACK_1_BYTE_PARAM((buf),(ATT_FIND_INFO_UUID_FRMT_OFFSET),(frmt))

#define ATT_PACK_ATTR_HANDLE(buf,offset,attr_hndl)\
        ATT_PACK_2_BYTE_PARAM((buf),(offset),(attr_hndl))

#define ATT_PACK_READ_BY_TYPE_LEN(buf,len)\
        ATT_PACK_1_BYTE_PARAM((buf),(ATT_READ_BY_TYPE_LENGH_OFFSET),(len))

#define ATT_PACK_READ_BY_GROUP_RSP_LEN(buf,len)\
        ATT_PACK_1_BYTE_PARAM((buf),(ATT_READ_BY_TYPE_LENGH_OFFSET),(len))

#define ATT_PACK_HANDLE_RANGE(buf,offset,range)\
        ATT_PACK_2_BYTE_PARAM((buf),(offset),&((range).start_handle));\
        ATT_PACK_2_BYTE_PARAM((buf),((offset)+ATT_ATTR_HANDLE_SIZE),\
        &((range).end_handle))

/* --------------------------------------------- Data Types/ Structures */

typedef BT_DEVICE_ADDR BLE_DEVICE_HANDLE;

typedef struct
{
    /* Device Handle */
    DEVICE_HANDLE        device_id;

#ifdef ATT_CNFRMD_REQUEST_SUPPORT
    /**
     * Spec Defined Timer for Response Timeout, applicable to Clients & Servers
     * supporting Indications
     */
    BT_timer_handle      timer_handle;
#endif /* ATT_CNFRMD_REQUEST_SUPPORT */

#ifdef ATT_MTU_UPDATE
    /* MTU being negotiated using Xchng MTU Req. Local Initiated */
    UINT16               ltemp_mtu;

    /* MTU being negotiated using Xchng MTU Req. Peer Initiated */
    UINT16               rtemp_mtu;

    /* MTU on the Instance */
    UINT16               mtu;
#endif /* ATT_MTU_UPDATE */

#if ((defined ATT_ON_BR_EDR_SUPPORT) || (defined ATT_ON_ECBFC_SUPPORT))
    UINT16               lcid;
#endif /* ((defined ATT_ON_BR_EDR_SUPPORT) || (defined ATT_ON_ECBFC_SUPPORT)) */

    /* Current State of ATT on the link */
    STATE_T              state;

    /* Response expected from Application for a pending request from Peer */
    UCHAR                expected_tx_rsp;

    /* Response expected from Application for a pending indication from peer */
    UCHAR                expected_tx_ind_rsp;

#ifdef ATT_CNFRMD_REQUEST_SUPPORT
    /* Response expected from Peer for a pending request from Application */
    UCHAR                expected_rx_rsp;
#endif /* ATT_CNFRMD_REQUEST_SUPPORT */

#ifdef ATT_ON_ECBFC_SUPPORT
    /* Channel Mode */
    UCHAR                channel_mode;

    /* Local MPS Value */
    UINT16               l_mps;

    /* Remote MPS Value */
    UINT16               r_mps;
#endif /* ATT_ON_ECBFC_SUPPORT */

}ATT_CONNECTION;

/* --------------------------------------------- Functions */
void att_l2cap_data_cb
     (
         /* IN */ DEVICE_HANDLE  * handle,
         /* IN */ UCHAR            l2cap_event,
         /* IN */ UCHAR          * pdu,
         /* IN */ UINT16           pdu_length
     );

API_RESULT att_pack_value
           (
               /* INOUT */ ATT_VALUE     * value,
               /* IN */    UCHAR         * buffer,
               /* IN */    UINT16        offset,
               /* IN */    ATT_CON_ID    att_id
           );

#ifdef ATT_READ_MULTIPLE_VARIABLE_LENGTH_SUPPORT
API_RESULT att_pack_length_value_tuple
           (
               /* INOUT */ ATT_VALUE     * value,
               /* IN */    UCHAR         * buffer,
               /* IN */    UINT16        offset,
               /* IN */    ATT_CON_ID    att_id,
               /* OUT */   UCHAR         * value_len_octets_packed
           );
#endif /* ATT_READ_MULTIPLE_VARIABLE_LENGTH_SUPPORT */

API_RESULT att_pack_handle_list
           (
               /* INOUT */ ATT_HANDLE_LIST    * list,
               /* IN */    UCHAR              * buffer,
               /* IN */    ATT_CON_ID         att_id
           );

API_RESULT att_pack_handle_uuid_pair
           (
               /* INOUT */ ATT_HANDLE_UUID_LIST   * list,
               /* IN */    UCHAR                  * buffer,
               /* IN */    UINT16                   offset,
               /* IN */    ATT_CON_ID               att_id,
               /* IN */    UCHAR                    uuid_format
           );

API_RESULT att_pack_handle_value_pair
           (
               /* INOUT */ ATT_HANDLE_VALUE_PAIR    * handle_value,
               /* IN */    UCHAR                    * buffer,
               /* IN */    UINT16                   offset,
               /* IN */    ATT_CON_ID               att_id,
               /* IN */    UCHAR                    pack_partial
           );

#ifdef ATT_HNDL_VAL_MULT_NOTIFICATION_SUPPORT
API_RESULT att_pack_handle_length_value_tuple
           (
               /* INOUT */ ATT_HANDLE_VALUE_PAIR    * handle_value,
               /* IN */    UCHAR                    * buffer,
               /* IN */    UINT16                   offset,
               /* IN */    ATT_CON_ID               att_id,
               /* IN */    UCHAR                    pack_partial
           );
#endif /* ATT_HNDL_VAL_MULT_NOTIFICATION_SUPPORT */

void att_notify_application
     (
        /* IN */ ATT_EVENT_INFO    * param,
        /* IN */ API_RESULT        retval
     );

void att_timer_cb(void *data_param, UINT16 datalen);

void att_fsm_set_state
     (
         /* IN */ ATT_CON_ID    att_id,
         /* IN */ STATE_T       state_info
     );

void att_fsm_change_state
     (
         /* IN */ ATT_EVENT_INFO   * param,
         /* IN */ STATE_T          state_info
     );

API_RESULT att_get_connection_instance
           (
               /* INOUT */ ATT_HANDLE    * handle
           );

#ifdef L2CAP_SUPPORT_ECBFC_MODE
API_RESULT att_get_connection_instance_with_state
           (
               /* INOUT */ ATT_HANDLE    * handle,
               /* IN */    UINT32          state
           );
#endif /* L2CAP_SUPPORT_ECBFC_MODE */

API_RESULT att_search_lcid_instance
           (
               /* IN */  UINT16         lcid,
               /* OUT */ ATT_HANDLE    * handle
           );

API_RESULT att_l2ca_connect_ind
           (
               /* IN */ DEVICE_HANDLE    * device_handle,
               /* IN */ UINT16             lcid,
               /* IN */ UINT16             psm
           );

API_RESULT att_l2ca_connect_cnf
           (
               /* IN */ DEVICE_HANDLE    * device_handle,
               /* IN */ UINT16             lcid,
               /* IN */ UINT16             result,
               /* IN */ UINT16             status
           );

API_RESULT att_l2ca_config_ind
           (
               /* IN */  UINT16                   lcid,
               /* IN */  L2CAP_CONFIG_OPTION    * rem_config_option
           );

API_RESULT att_l2ca_config_cnf
           (
               /* IN */  UINT16                 lcid,
               /* IN */  UINT16                 result,
               /* IN */ L2CAP_CONFIG_OPTION *  config_option
           );

API_RESULT att_l2cap_procedure_complete
           (
               /* IN */ ATT_HANDLE    * handle
           );

API_RESULT att_l2ca_disconnect_ind
           (
               /* IN */ UINT16  lcid
           );

API_RESULT att_l2ca_disconnect_cnf
           (
               /* IN */ UINT16  lcid,
               /* IN */ UINT16  result
           );

API_RESULT att_l2ca_data_read
           (
               /* IN */ UINT16  lcid,
               /* IN */ UCHAR * data,
               /* IN */ UINT16  datalen
           );

API_RESULT att_l2ca_tx_flow_ind
           (
               /* IN */ UINT16   lcid,
               /* IN */ UCHAR    flow_cntrl_flg
           );

API_RESULT att_l2cap_write
           (
               /* IN */ ATT_HANDLE    * handle,
               /* IN */ UCHAR         * data,
               /* IN */ UINT16        data_len
           );

#ifdef L2CAP_SUPPORT_ECBFC_MODE
API_RESULT att_l2ca_ecbfc_connect_ind_cb
           (
               DEVICE_HANDLE            * handle,
               UINT16                   * lcid,
               UINT16                     psm,
               L2CAP_ECBFC_CONNECT_PARAM * param
           );

API_RESULT att_l2ca_ecbfc_connect_cnf_cb
           (
               DEVICE_HANDLE             * handle,
               UINT16                    * lcid,
               UINT16                      response,
               L2CAP_ECBFC_CONNECT_PARAM * param
           );

API_RESULT att_l2ca_ecbfc_reconfig_ind_cb
           (
               DEVICE_HANDLE              * handle,
               UINT16                     * lcid,
               L2CAP_ECBFC_RECONFIG_PARAM * param
           );

API_RESULT att_l2ca_ecbfc_reconfig_cnf_cb
           (
               DEVICE_HANDLE            * handle
           );

API_RESULT att_l2ca_ecbfc_disconnect_ind_cb(UINT16 lcid);

API_RESULT att_l2ca_ecbfc_disconnect_cnf_cb(UINT16 lcid, UINT16 reason);

API_RESULT att_l2ca_ecbfc_data_read_cb(UINT16 lcid, UINT16 result, UCHAR * data, UINT16 datalen);

API_RESULT att_l2ca_ecbfc_low_rx_credit_ind_cb(UINT16 lcid, UINT16 credit);

API_RESULT att_l2ca_ecbfc_tx_credit_ind_cb(UINT16 lcid, UINT16 result, UINT16 credit);

API_RESULT att_l2ca_ecbfc_data_write_cb(UINT16 lcid, UINT16 result, UCHAR *buffer, UINT16 buffer_len);

#endif /* L2CAP_SUPPORT_ECBFC_MODE */

API_RESULT att_transport_write
           (
               /* IN */ ATT_EVENT_INFO    * param
           );

/* To be moved to pl file. */
#define att_transport_pl_write(i,d,dl)\
        l2cap_fixed_channel_data_write\
        (\
            (i),\
            L2CAP_ATT_CID,\
            (d),\
            (dl)\
        )

EVENT_T att_get_fsm_event(UCHAR op_code);

#ifdef BT_STORAGE
#ifdef STORAGE_RETENTION_SUPPORT
void att_rstorage_cb (UCHAR id, UCHAR type, UCHAR action);
#endif /* STORAGE_RETENTION_SUPPORT */
#endif /* BT_STORAGE */

#endif /* _H_ATT_INTERNAL_ */
